<?php namespace hdphp\route;

use Closure;

class Compile extends Setting
{
    //路由参数
    protected $args = array();

    /**
     * 匹配路由
     *
     * @param  [type]  $key
     *
     * @return boolean
     */
    protected function isMatch ($key)
    {
        if (preg_match ($this->route[$key]['regexp'], $this->requestUri))
        {
            //获取参数
            $this->route[$key]['get'] = $this->getArgs ($key);
            //验证参数
            if ( ! $this->checkArgs ($key))
            {
                return false;
            }
            //设置GET参数
            $this->args = $_GET = array_merge ($this->route[$key]['get'], $_GET);

            return $this->found = true;
        }
    }

    /**
     * 获取请求参数
     *
     * @param  [type] $key [description]
     *
     * @return [type]      [description]
     */
    protected function getArgs ($key)
    {
        $args = array();

        if (preg_match_all ($this->route[$key]['regexp'], $this->requestUri, $matched, PREG_SET_ORDER))
        {
            //参数列表
            foreach ($this->route[$key]['args'] as $n => $value)
            {
                if (isset($matched[0][$n + 1]))
                {
                    $args[$value[1]] = $matched[0][$n + 1];
                }
            }
        }

        return $args;
    }

    /**
     * 验证路由参数
     *
     * @param  [int] $key [description]
     *
     * @return [bool]      [description]
     */
    protected function checkArgs ($key)
    {
        $route = $this->route[$key];

        if ( ! empty($route['where']))
        {
            foreach ($route['where'] as $name => $regexp)
            {
                if (isset($route['get'][$name]) && ! preg_match ($regexp, $route['get'][$name]))
                {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * 执行路由事件
     *
     * @param  [type] $route [description]
     *
     * @return [type]        [description]
     */
    public function exec ($key)
    {
        //匿名函数
        if ($this->route[$key]['callback'] instanceof Closure)
        {
            echo call_user_func_array ($this->route[$key]['callback'], $this->route[$key]['get']);
            exit;
        }
        else
        {
            //设置控制器与方法
            $data = explode ('/', $this->route[$key]['callback']);

            define ('ACTION', array_pop ($data));
            define ('CONTROLLER', array_pop ($data));
            define ('MODULE', array_pop ($data));

            return $this->found = true;
        }
    }

    /**
     * GET事件处理
     *
     * @param $key
     *
     * @return bool
     */
    protected function _get ($key)
    {
        return IS_GET && $this->isMatch ($key) && $this->exec ($key);
    }

    /**
     * POST事件处理
     *
     * @param  [type] $route [description]
     *
     * @return [type]        [description]
     */
    protected function _post ($key)
    {
        return IS_POST && $this->isMatch ($key) && $this->exec ($key);
    }

    /**
     * POST事件处理
     *
     * @param  [type] $route [description]
     *
     * @return [type]        [description]
     */
    protected function _put ($key)
    {
        if (empty($_POST))
        {
            parse_str (file_get_contents ('php://input'), $_POST);
        }

        return IS_PUT && $this->isMatch ($key) && $this->exec ($key);
    }

    /**
     * POST事件处理
     *
     * @param  [type] $route [description]
     *
     * @return [type]        [description]
     */
    protected function _delete ($key)
    {
        if (empty($_POST))
        {
            parse_str (file_get_contents ('php://input'), $_POST);
        }

        return IS_DELETE && $this->isMatch ($key) && $this->exec ($key);
    }


    /**
     * 任意提交模式
     *
     * @param  [type] $route [description]
     *
     * @return [type]        [description]
     */
    protected function _any ($key)
    {
        return $this->isMatch ($key) && $this->exec ($key);
    }

    /**
     * 任意提交模式
     *
     * @param  [type] $route [description]
     *
     * @return [type]        [description]
     */
    protected function _controller ($key)
    {
        if ($this->route[$key]['method'] == 'controller' && $this->isMatch ($key))
        {
            //控制器方法
            $method = $this->getRequestAction ().ucfirst ($this->route[$key]['get']['method']);

            //从容器提取控制器对象
            $info = explode ('/', $this->route[$key]['callback']);
            define ('MODULE', array_shift ($info));
            define ('CONTROLLER', array_shift ($info));
            define ('ACTION', $method);
            $this->found = true;
        }
    }

    /**
     * 获取请求方法
     * @return string
     */
    public function getRequestAction ()
    {
        switch (true)
        {
            case IS_GET:
                return 'get';
            case IS_POST:
                return 'post';
            case IS_PUT:
                return 'put';
            case IS_DELETE:
                return 'delete';
        }
    }

    /**
     * 没有路由匹配时解析GET模式
     */
    public function RunGetModel ()
    {
        //URL结构处理
        $param = array();
        if (isset($_GET[c('http.url_var')]))
        {
            $param = explode ('/', $_GET[c('http.url_var')]);
            unset($_GET[c('http.url_var')]);
        }
        switch (count ($param))
        {
            case 3:
                define ('MODULE', array_shift ($param));
                define ('CONTROLLER', array_shift ($param));
                define ('ACTION', array_shift ($param));
                break;
            case 2:
                define ('CONTROLLER', array_shift ($param));
                define ('ACTION', array_shift ($param));
                break;
            case 1:
                define ('ACTION', array_shift ($param));
                break;
        }

        if ( ! defined ('MODULE'))
        {
            define ('MODULE', defined ('BIND_MODULE') ? BIND_MODULE : C ('http.default_module'));
        }
        if ( ! defined ('CONTROLLER'))
        {
            define ('CONTROLLER', C ('http.default_controller'));
        }
        if ( ! defined ('ACTION'))
        {
            define ('ACTION', C ('http.default_action'));
        }
        $this->found = true;
    }

    /**
     * 获取解析后的参数
     *
     * @return mixed
     */
    public function getArg ()
    {
        return $this->args;
    }
}